Attacks in the forms of, e.g., viruses and worms, are among the most prominent security concerns for software developers. Software, including operating systems and applications, both singularly and in combination, are vulnerable to attacks primarily due to programming errors. These attacks, also referred to as security breaches, on operating systems and/or applications typically fall into one of the three categories: low-level attacks, semantic-level attacks, and configuration-error attacks.
The first step towards breach-proof software is bug-free programming. However, a pragmatic perspective on the increasingly demanding task of programming leads to the realization that programming bugs are inevitable as applications continue to increase in sophistication. Static-analysis tools have proven effective for catching a large number of programming bugs that fit known patterns, but they still leave the programs vulnerable to more complex forms of attack. Further, the use of safe programming languages such as C# eliminates some classes of low-level vulnerabilities such as a buffer-overrun vulnerability, but performance is sacrificed by using such languages. That is, such languages are not conducive to more sophisticated forms of programming. Furthermore, parts of the run-time system and the just-in-time compiler, written in traditional C/C++ languages, still contain bugs.
Previous efforts at eliminating security breaches on software include run-time defense mechanisms. For example, bounds checkers can detect and stop buffer-overrun intrusions, but they require significant performance overhead. In addition, systems such as StackGuard and Microsoft® .NET® C/C++ compiler can transform a program to effectively catch buffer overruns on a stack. However, these systems are unable to catch buffer overruns in a heap, and their effectiveness against future, yet-to-be-invented attacks, is dubious. Further still, system-level techniques intending to prevent direct execution of injected malicious, or invalid, code are unable to stop indirect execution of the injected code via carefully-crafted buffer overruns.